{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "06a3bbec",
   "metadata": {},
   "source": [
    "下面用代码实现循环神经网络。首先读取数据，使用《小王子》这本书作为训练语料。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "58df11c1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "115\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import os\n",
    "import sys\n",
    "\n",
    "# 导入前面实现的小王子数据集\n",
    "sys.path.append('./code')\n",
    "from my_utils import TheLittlePrinceDataset\n",
    "\n",
    "dataset = TheLittlePrinceDataset()\n",
    "\n",
    "# 统计每句话的长度\n",
    "sent_lens = []\n",
    "max_len = -1\n",
    "for sentence in dataset.tokens:\n",
    "    sent_len = len(sentence)\n",
    "    sent_lens.append(sent_len)\n",
    "    if sent_len > max_len:\n",
    "        max_len = sent_len\n",
    "        longest = sentence\n",
    "print(max_len)\n",
    "\n",
    "# 简单看一下语料中序列长度的分布\n",
    "import matplotlib.pyplot as plt\n",
    "plt.hist(sent_lens, bins=20)\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bf1e69d9",
   "metadata": {},
   "source": [
    "接下来建立词表，截断过长的序列，将序列填充（padding）到相同长度。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "f25456ee",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1089 115\n",
      "(1088, 40)\n",
      "[  4  16  19 733 734 735 733 734 735   2  63  20   9   1   1   2   1  10\n",
      " 736 737   4  16  19  21   1   2  30 371 209  33 294   3   0   0   0   0\n",
      "   0   0   0   0]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "dataset.build_vocab()\n",
    "sent_tokens = dataset.convert_tokens_to_ids()\n",
    "# 截断和填充\n",
    "max_len=40\n",
    "for i, tokens in enumerate(sent_tokens):\n",
    "    tokens = tokens[:max_len]\n",
    "    tokens += [dataset.token2id['<pad>']] * (max_len - len(tokens))\n",
    "    sent_tokens[i] = tokens\n",
    "sent_tokens = np.array(sent_tokens)\n",
    "\n",
    "print(len(dataset.tokens), max([len(x) for x in dataset.tokens]))\n",
    "print(sent_tokens.shape)\n",
    "print(sent_tokens[0])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "06e6fb52",
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "部分代码参考了GitHub项目d2l-ai/d2l-zh的思路\n",
    "（Copyright (c) 2022 Aston Zhang, Zachary C. Lipton,\n",
    "Mu Li, and Alexander J. Smola, Apache-2.0 License（见附录））\n",
    "\"\"\"\n",
    "import torch\n",
    "from torch import nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "# 定义一个正态分布的函数用于初始化参数\n",
    "def normal(shape):\n",
    "    return torch.randn(size=shape) * 0.01\n",
    "\n",
    "class RNN(nn.Module):\n",
    "    def __init__(self, input_size, hidden_size):\n",
    "        super(RNN, self).__init__()\n",
    "        self.input_size = input_size\n",
    "        self.hidden_size = hidden_size\n",
    "        # 将输入与隐状态分别经过线性变化后相加\n",
    "        self.W_xh = nn.Parameter(normal((input_size, hidden_size)))\n",
    "        self.W_hh = nn.Parameter(normal((hidden_size, hidden_size)))\n",
    "        self.b_h = nn.Parameter(torch.zeros(hidden_size))\n",
    "    \n",
    "    def init_rnn_state(self, batch_size, hidden_size):\n",
    "        return (torch.zeros((batch_size, hidden_size), dtype=torch.float),)\n",
    "    \n",
    "    def forward(self, inputs, states):\n",
    "        seq_len, batch_size, _ = inputs.shape\n",
    "        hidden_state, = states\n",
    "        hiddens = []\n",
    "        for step in range(seq_len):\n",
    "            # 输入hidden_state与inputs经过线性变换后相加，\n",
    "            # 输出的hidden_state也是下一时刻输入的hidden_state\n",
    "            xh = torch.mm(inputs[step], self.W_xh)\n",
    "            hh = torch.mm(hidden_state, self.W_hh)\n",
    "            hidden_state = xh + hh + self.b_h\n",
    "            hidden_state = torch.tanh(hidden_state)\n",
    "            hiddens.append(hidden_state)\n",
    "        # 返回所有时刻的hidden_state: seq_len * batch_size * hidden_size\n",
    "        # 以及最后时刻的hidden_state（可能用于后续输入）: \n",
    "        # batch_size * hidden_size\n",
    "        return torch.stack(hiddens, dim=0), (hidden_state,)\n",
    "\n",
    "# 在循环神经网络的基础上添加语言模型的输入输出、损失计算等\n",
    "class RNNLM(nn.Module):\n",
    "    def __init__(self, model, vocab_size, hidden_size):\n",
    "        super(RNNLM, self).__init__()\n",
    "        self.vocab_size = vocab_size\n",
    "        self.hidden_size = hidden_size\n",
    "        self.embedding = nn.Embedding(vocab_size, hidden_size)\n",
    "        self.model = model\n",
    "        self.W_hq = nn.Parameter(normal((hidden_size, vocab_size)))\n",
    "        self.b_q = nn.Parameter(torch.zeros(vocab_size))\n",
    "        \n",
    "    def forward(self, input_ids):\n",
    "        batch_size, seq_len = input_ids.shape\n",
    "        # input_ids形状为batch_size * seq_len，翻转为seq_len * batch_size，\n",
    "        # 将seq_len放在第一维方便计算\n",
    "        input_ids = torch.permute(input_ids, (1, 0))\n",
    "        # seq_len * batch_size * embed_size\n",
    "        embed = self.embedding(input_ids)\n",
    "        # batch_size * hidden_size\n",
    "        states = self.model.init_rnn_state(batch_size, self.hidden_size)\n",
    "        hiddens, _ = self.model(embed, states)\n",
    "    \n",
    "        hiddens = torch.flatten(hiddens[:-1], start_dim=0, end_dim=1)\n",
    "        output_states = torch.mm(hiddens, self.W_hq) + self.b_q\n",
    "        labels = torch.flatten(input_ids[1:], start_dim=0, end_dim=1)\n",
    "        loss_fct = nn.CrossEntropyLoss(ignore_index=0)\n",
    "        loss = loss_fct(output_states, labels)\n",
    "        return loss"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "45a010aa",
   "metadata": {},
   "source": [
    "下面展示使用梯度裁剪的循环神经网络语言模型的训练代码。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "760da2e1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1088, 40)\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "epoch-199, loss=0.3501: 100%|█| 200/200 [02:26<00:00,  1.36i\n"
     ]
    },
    {
     "data": {
      "image/png": "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ZUaNGsWwYcNOeKw3vY8n+nxozu/Q1NRUtm3b5hY6ncF74MCBrVaoHOHdd981/P39jddee83YsWOHcfPNNxsRERFuM5o7kltvvdUIDw83li5dauTk5Li+qqurDcMwjLS0NOPRRx811q9fb6Snpxuffvqp0bNnT2PSpEkerrx57r33XmPp0qVGenq68eOPPxpTp041YmJijPz8fMMwDOOWW24xUlJSjMWLFxvr1683UlNTjdTUVA9XffJsNpuRkpJi3H///W73d9T3r6Kiwti0aZOxadMmAzCefvppY9OmTa6rXh5//HEjIiLC+PTTT42tW7cas2bNMnr06GHU1NS4XmP69OnGiBEjjDVr1hgrVqww+vTpY8yePdtTp+TmeOdXV1dnXHTRRUZSUpKxefNmt3+XzqskVq5caTzzzDPG5s2bjX379hlvvvmmERsba1x99dUePrPDjneOFRUVxn333WesWrXKSE9PNxYtWmSMHDnS6NOnj1FbW+t6DW9+Dw3jxH9PDcMwysrKjKCgIGPBggVHPd/b38cTfT4Yxol/hzY0NBiDBw82zjvvPGPz5s3GN998Y8TGxhpz585ttToVVJrwwgsvGCkpKYafn58xduxYY/Xq1Z4uqcWAJr9effVVwzAMIzMz05g0aZIRFRVl+Pv7G7179zZ+97vfGWVlZZ4tvJmuuOIKo0uXLoafn5/RtWtX44orrjDS0tJcj9fU1Bi/+c1vjMjISCMoKMi45JJLjJycHA9W3DLffvutARi7d+92u7+jvn9Llixp8u/lNddcYxiG4xLlBx54wIiPjzf8/f2NKVOmHHXuRUVFxuzZs42QkBAjLCzMuO6664yKigoPnM3Rjnd+6enpx/x3uWTJEsMwDGPDhg3GuHHjjPDwcCMgIMAYMGCA8dhjj7l9yHva8c6xurraOO+884zY2FjD19fX6Natm3HTTTcd9T983vweGsaJ/54ahmG89NJLRmBgoFFaWnrU8739fTzR54NhNO93aEZGhjFjxgwjMDDQiImJMe69916jvr6+1eo0NRYrIiIi4nU0R0VERES8loKKiIiIeC0FFREREfFaCioiIiLitRRURERExGspqIiIiIjXUlARERERr6WgIiIiIl5LQUVEmqV79+48++yzzT5+6dKlmEymozY066xO9s9HRJrHx9MFiEjbmDx5MsOHD2+1D89169YRHBzc7OPHjx9PTk4O4eHhrfLzReT0pKAichozDAObzYaPz4l/FcTGxp7Ua/v5+bXaNu8icvrS0I9IJ3TttdeybNkynnvuOUwmEyaTiYyMDNdwzNdff82oUaPw9/dnxYoV7Nu3j1mzZhEfH09ISAhjxoxh0aJFbq/586ENk8nEv//9by655BKCgoLo06cPn332mevxnw/9vPbaa0RERPDtt98yYMAAQkJCmD59Ojk5Oa7nNDQ0cOeddxIREUF0dDT3338/11xzDRdffPFxz3fFihVMnDiRwMBAkpOTufPOO6mqqnKr/c9//jOzZ88mODiYrl27Mn/+fLfXyMzMZNasWYSEhBAWFsbll19OXl6e2zGff/45Y8aMISAggJiYGC655BK3x6urq7n++usJDQ0lJSWFf/7zn8etW0ROTEFFpBN67rnnSE1N5aabbiInJ4ecnBySk5Ndj//hD3/g8ccfZ+fOnQwdOpTKykrOP/98vv/+ezZt2sT06dOZOXMmmZmZx/05jzzyCJdffjlbt27l/PPPZ86cORQXFx/z+Orqav7+97/zn//8h+XLl5OZmcl9993nevxvf/sbb731Fq+++io//vgj5eXlfPLJJ8etYd++fUyfPp3LLruMrVu38t5777FixQpuv/12t+OefPJJhg0bxqZNm/jDH/7AXXfdxcKFCwGw2+3MmjWL4uJili1bxsKFC9m/fz9XXHGF6/lffvkll1xyCeeffz6bNm3i+++/Z+zYsW4/46mnnmL06NFs2rSJ3/zmN9x6663s3r37uPWLyAm02j7MIuJVzjrrLOOuu+5yu8+5bf0nn3xywucPGjTIeOGFF1y3u3XrZjzzzDOu24Dxpz/9yXW7srLSAIyvv/7a7WeVlJQYhmEYr776qgEYaWlprufMnz/fiI+Pd92Oj483nnzySdfthoYGIyUlxZg1a9Yx67zhhhuMm2++2e2+H374wTCbzUZNTY2r9unTp7sdc8UVVxgzZswwDMMwvvvuO8NisRiZmZmux7dv324Axtq1aw3DMIzU1FRjzpw5x6yjW7duxq9+9SvXbbvdbsTFxRkLFiw45nNE5MTUURE5DY0ePdrtdmVlJffddx8DBgwgIiKCkJAQdu7cecKOytChQ13fBwcHExYWRn5+/jGPDwoKolevXq7bXbp0cR1fVlZGXl6eW5fCYrEwatSo49awZcsWXnvtNUJCQlxf06ZNw263k56e7jouNTXV7Xmpqans3LkTgJ07d5KcnOzWdRo4cCARERGuYzZv3syUKVOOW8uRfx4mk4mEhITj/nmIyIlpMq3IaejnV+/cd999LFy4kL///e/07t2bwMBAfvGLX1BXV3fc1/H19XW7bTKZsNvtJ3W8YRgnWb27yspKfv3rX3PnnXce9VhKSsopvfaRAgMDT3jMyf55iMiJqaMi0kn5+flhs9madeyPP/7ItddeyyWXXMKQIUNISEggIyOjbQv8mfDwcOLj41m3bp3rPpvNxsaNG4/7vJEjR7Jjxw569+591Jefn5/ruNWrV7s9b/Xq1QwYMACAAQMGkJWVRVZWluvxHTt2UFpaysCBAwFHt+T7778/5fMUkZOjjopIJ9W9e3fWrFlDRkYGISEhREVFHfPYPn368NFHHzFz5kxMJhMPPPCARzoBd9xxB/PmzaN3797079+fF154gZKSEkwm0zGfc//993PGGWdw++23c+ONNxIcHMyOHTtYuHAhL774ouu4H3/8kSeeeIKLL76YhQsX8sEHH/Dll18CMHXqVIYMGcKcOXN49tlnaWho4De/+Q1nnXWWa5jsoYceYsqUKfTq1Ysrr7yShoYGvvrqK+6///62/UMROc2poyLSSd13331YLBYGDhxIbGzsceebPP3000RGRjJ+/HhmzpzJtGnTGDlyZDtW63D//fcze/Zsrr76alJTU13zTQICAo75nKFDh7Js2TL27NnDxIkTGTFiBA8++CCJiYlux917772sX7+eESNG8Je//IWnn36aadOmAY4hmk8//ZTIyEgmTZrE1KlT6dmzJ++9957r+ZMnT+aDDz7gs88+Y/jw4ZxzzjmsXbu2bf4gRMTFZJzqALGISBux2+0MGDCAyy+/nD//+c8tfp3u3btz9913c/fdd7decSLSLjT0IyJe48CBA3z33XecddZZWK1WXnzxRdLT07nqqqs8XZqIeIiGfkTEa5jNZl577TXGjBnDhAkT2LZtG4sWLXJNehWR04+GfkRERMRrqaMiIiIiXktBRURERLyWgoqIiIh4LQUVERER8VoKKiIiIuK1FFRERETEaymoiIiIiNdSUBERERGv9f9qI0Q76SUTSgAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 梯度裁剪\n",
    "def grad_clipping(model, theta=1):\n",
    "    params = [p for p in model.parameters() if p.requires_grad]\n",
    "    norm = torch.sqrt(sum(torch.sum((p.grad ** 2)) for p in params))\n",
    "    if norm > theta:\n",
    "        for param in params:\n",
    "            param.grad[:] *= theta / norm\n",
    "    \n",
    "\n",
    "# 训练\n",
    "from torch.utils.data import DataLoader\n",
    "from torch.optim import SGD, Adam\n",
    "import numpy as np\n",
    "from tqdm import tqdm, trange\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "def train_rnn_lm(data_loader, rnn, vocab_size, hidden_size=128, \n",
    "                 epochs=200, learning_rate=1e-3):\n",
    "    # 准备模型、优化器等\n",
    "    rnn_lm = RNNLM(rnn, vocab_size, hidden_size)\n",
    "    optimizer = Adam(rnn_lm.parameters(), lr=learning_rate)\n",
    "    rnn_lm.zero_grad()\n",
    "    rnn_lm.train()\n",
    "\n",
    "    epoch_loss = []\n",
    "    with trange(epochs, desc='epoch', ncols=60) as pbar:\n",
    "        for epoch in pbar:\n",
    "            for step, batch in enumerate(data_loader):\n",
    "                loss = rnn_lm(batch)\n",
    "                pbar.set_description(f'epoch-{epoch}, ' + \\\n",
    "                    f'loss={loss.item():.4f}')\n",
    "                loss.backward()\n",
    "                grad_clipping(rnn_lm)\n",
    "                optimizer.step()\n",
    "                rnn_lm.zero_grad()\n",
    "            epoch_loss.append(loss.item())\n",
    "\n",
    "    epoch_loss = np.array(epoch_loss)\n",
    "    # 打印损失曲线\n",
    "    plt.plot(range(len(epoch_loss)), epoch_loss)\n",
    "    plt.xlabel('training epoch')\n",
    "    plt.ylabel('loss')\n",
    "    plt.show()\n",
    "\n",
    "sent_tokens = np.array(sent_tokens)\n",
    "print(sent_tokens.shape)\n",
    "vocab_size = len(dataset.token2id)\n",
    "\n",
    "data_loader = DataLoader(torch.tensor(sent_tokens, dtype=torch.long),\\\n",
    "    batch_size=16, shuffle=True)\n",
    "rnn = RNN(128, 128)\n",
    "train_rnn_lm(data_loader, rnn, vocab_size, hidden_size=128,\\\n",
    "    epochs=200, learning_rate=1e-3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ad30e705",
   "metadata": {},
   "source": [
    "接下来仿照循环神经网络实现长短期记忆，同样的接口使得我们可以重用之前的训练代码。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "1995d027",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "epoch-199, loss=0.3962: 100%|█| 200/200 [07:01<00:00,  2.11s\n"
     ]
    },
    {
     "data": {
      "image/png": "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n66oqFQqxMTE9Oh7+Pn59du/eED/vz+A99gf9Pf7A3iP/UF/vz/AuffYWSXFjoNpiYiIyG0xqBAREZHbYlDpgE6nwzPPPAOdTufqpvSI/n5/AO+xP+jv9wfwHvuD/n5/gGvvsU8PpiUiIqL+jRUVIiIiclsMKkREROS2GFSIiIjIbTGoEBERkdtiUGnHypUrkZCQAE9PT0ycOBF79+51dZO6bcWKFRg/fjx8fX0RFhaGG264AadPn3Y4ZsaMGZAkyeHr/vvvd1GLL82f/vSnNm0fOnSo8npzczOWLl2K4OBg6PV63HjjjSgpKXFhiy9dQkJCm3uUJAlLly4F0Dc/v23btmHBggWIioqCJElYu3atw+tCCDz99NOIjIyEl5cXZs+ejbNnzzocU1lZiSVLlsDPzw8BAQG4++67UV9f34t30bGL3Z/JZMKyZcswatQo+Pj4ICoqCrfddhsKCwsdrtHe5/7CCy/08p10rLPP8I477mjT/nnz5jkc486fIdD5Pbb371KSJLz00kvKMe78OXbl90NXfobm5eXh2muvhbe3N8LCwvCb3/wGZrPZae1kULnAZ599hieeeALPPPMMDh48iNGjR2Pu3LkoLS11ddO6ZevWrVi6dCl2796N9evXw2QyYc6cOWhoaHA47t5770VRUZHy9eKLL7qoxZduxIgRDm3fvn278trjjz+O//znP/jiiy+wdetWFBYW4mc/+5kLW3vp9u3b53B/69evBwD84he/UI7pa59fQ0MDRo8ejZUrV7b7+osvvojXX38db731Fvbs2QMfHx/MnTsXzc3NyjFLlizB8ePHsX79enz77bfYtm0b7rvvvt66hYu62P01Njbi4MGD+OMf/4iDBw9izZo1OH36NK6//vo2xz777LMOn+vDDz/cG83vks4+QwCYN2+eQ/v/9a9/Obzuzp8h0Pk9tr63oqIivPfee5AkCTfeeKPDce76OXbl90NnP0MtFguuvfZaGI1G7Ny5Ex988AFWr16Np59+2nkNFeRgwoQJYunSpcpji8UioqKixIoVK1zYKucpLS0VAMTWrVuV56ZPny4effRR1zXqMjzzzDNi9OjR7b5WXV0tPDw8xBdffKE8d/LkSQFA7Nq1q5da6HyPPvqoSEpKElarVQjRtz8/IYQAIL766ivlsdVqFREREeKll15SnquurhY6nU7861//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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\"\"\"\n",
    "部分代码参考了GitHub项目d2l-ai/d2l-zh的思路\n",
    "（Copyright (c) 2022 Aston Zhang, Zachary C. Lipton,\n",
    "Mu Li, and Alexander J. Smola, Apache-2.0 License（见附录））\n",
    "\"\"\"\n",
    "# 长短期记忆\n",
    "def gate_params(input_size, hidden_size):\n",
    "    return (nn.Parameter(normal((input_size, hidden_size))),\n",
    "           nn.Parameter(normal((hidden_size, hidden_size))),\n",
    "           nn.Parameter(torch.zeros(hidden_size)))\n",
    "\n",
    "class LSTM(nn.Module):\n",
    "    def __init__(self, input_size, hidden_size):\n",
    "        super(LSTM, self).__init__()\n",
    "        self.input_size = input_size\n",
    "        self.hidden_size = hidden_size\n",
    "        # 输入门参数\n",
    "        self.W_xi, self.W_hi, self.b_i = gate_params(input_size, hidden_size)\n",
    "        # 遗忘门参数\n",
    "        self.W_xf, self.W_hf, self.b_f = gate_params(input_size, hidden_size)\n",
    "        # 输出门参数\n",
    "        self.W_xo, self.W_ho, self.b_o = gate_params(input_size, hidden_size)\n",
    "        # 候选记忆单元参数\n",
    "        self.W_xc, self.W_hc, self.b_c = gate_params(input_size, hidden_size)\n",
    "        \n",
    "    def init_rnn_state(self, batch_size, hidden_size):\n",
    "        return (torch.zeros((batch_size, hidden_size), dtype=torch.float),\n",
    "               torch.zeros((batch_size, hidden_size), dtype=torch.float))\n",
    "    \n",
    "    def forward(self, inputs, states):\n",
    "        seq_len, batch_size, _ = inputs.shape\n",
    "        hidden_state, cell_state = states\n",
    "        hiddens = []\n",
    "        for step in range(seq_len):\n",
    "            I = torch.sigmoid(torch.mm(inputs[step], self.W_xi) \\\n",
    "                + torch.mm(hidden_state, self.W_hi) + self.b_i)\n",
    "            F = torch.sigmoid(torch.mm(inputs[step], self.W_xf) \\\n",
    "                + torch.mm(hidden_state, self.W_hf) + self.b_f)\n",
    "            O = torch.sigmoid(torch.mm(inputs[step], self.W_xo) \\\n",
    "                + torch.mm(hidden_state, self.W_ho) + self.b_o)\n",
    "            C_tilda = torch.tanh(torch.mm(inputs[step], self.W_xc) \\\n",
    "                + torch.mm(hidden_state, self.W_hc) + self.b_c)\n",
    "            cell_state = F * cell_state + I * C_tilda\n",
    "            hidden_state = O * torch.tanh(cell_state)\n",
    "            hiddens.append(hidden_state)\n",
    "        return torch.stack(hiddens, dim=0), (hidden_state, cell_state)\n",
    "    \n",
    "data_loader = DataLoader(torch.tensor(sent_tokens, dtype=torch.long), \n",
    "    batch_size=16, shuffle=True)\n",
    "\n",
    "lstm = LSTM(128, 128)\n",
    "train_rnn_lm(data_loader, lstm, vocab_size, hidden_size=128, epochs=200, \n",
    "    learning_rate=1e-3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e6dafe1d",
   "metadata": {},
   "source": [
    "下面仿照长短期记忆实现门控循环单元。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "7c4f3992",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "epoch-199, loss=0.2323: 100%|█| 200/200 [06:19<00:00,  1.90s\n"
     ]
    },
    {
     "data": {
      "image/png": "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55/PrFmzuO222wgODmbnzp0sWrSIl156yXXcqlWreOqpp7jyyitZtGgR77//Pp9//jkAEydOpH///syYMYPnn3+empoa7rnnHsaNG+fqJnvssceYMGECqamp/PSnP6WmpoYvvviC2bNnt+wfisg5Ti0qIu3UQw89hI+PD3369CE2Nva0402effZZIiMjGTVqFFOnTmXSpEkMHjy4Fau1mz17NtOnT+fGG29k5MiRrvEmAQEBpzxnwIABLF++nD179jBmzBgGDRrEo48+SmJiottxDz74IBs2bGDQoEH86U9/4tlnn2XSpEmAvYvm448/JjIykrFjxzJx4kS6du3KggULXOePHz+e999/n08++YTzzjuPiy66iHXr1rXMH4SIuJiMs+0gFhFpITabjd69e3PdddfxxBNPNPl9OnfuzP3338/999/ffMWJSKtQ14+IeI2DBw/yzTffMG7cOCorK3nppZdIT0/nhhtu8HRpIuIh6voREa9hNpuZP38+w4YNY/To0Wzbto3Fixe7Br2KyLlHXT8iIiLitdSiIiIiIl5LQUVERES8loKKiIiIeC0FFREREfFaCioiIiLitRRURERExGspqIiIiIjXUlARERERr/X/XnT2CQaGFbEAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\"\"\"\n",
    "部分代码参考了GitHub项目d2l-ai/d2l-zh的思路\n",
    "（Copyright (c) 2022 Aston Zhang, Zachary C. Lipton,\n",
    "Mu Li, and Alexander J. Smola, Apache-2.0 License（见附录））\n",
    "\"\"\"\n",
    "# 门控循环单元\n",
    "class GRU(nn.Module):\n",
    "    def __init__(self, input_size, hidden_size):\n",
    "        super(GRU, self).__init__()\n",
    "        self.input_size = input_size\n",
    "        self.hidden_size = hidden_size\n",
    "        # 更新门参数\n",
    "        self.W_xu, self.W_hu, self.b_u = gate_params(input_size, hidden_size)\n",
    "        # 重置门参数\n",
    "        self.W_xr, self.W_hr, self.b_r = gate_params(input_size, hidden_size)\n",
    "        # 候选隐状态参数\n",
    "        self.W_xh, self.W_hh, self.b_h = gate_params(input_size, hidden_size)\n",
    "        \n",
    "    def init_rnn_state(self, batch_size, hidden_size):\n",
    "        return (torch.zeros((batch_size, hidden_size), dtype=torch.float),)\n",
    "    \n",
    "    def forward(self, inputs, states):\n",
    "        seq_len, batch_size, _ = inputs.shape\n",
    "        hidden_state, = states\n",
    "        hiddens = []\n",
    "        for step in range(seq_len):\n",
    "            U = torch.sigmoid(torch.mm(inputs[step], self.W_xu)\\\n",
    "                + torch.mm(hidden_state, self.W_hu) + self.b_u)\n",
    "            R = torch.sigmoid(torch.mm(inputs[step], self.W_xr)\\\n",
    "                + torch.mm(hidden_state, self.W_hr) + self.b_r)\n",
    "            H_tilda = torch.tanh(torch.mm(inputs[step], self.W_xh)\\\n",
    "                + torch.mm(R * hidden_state, self.W_hh) + self.b_h)\n",
    "            hidden_state = (1 - U) * hidden_state + U * H_tilda\n",
    "            hiddens.append(hidden_state)\n",
    "        return torch.stack(hiddens, dim=0), (hidden_state,)\n",
    "    \n",
    "data_loader = DataLoader(torch.tensor(sent_tokens, dtype=torch.long), \n",
    "    batch_size=16, shuffle=True)\n",
    "\n",
    "gru = GRU(128, 128)\n",
    "train_rnn_lm(data_loader, gru, vocab_size, hidden_size=128, epochs=200, \n",
    "    learning_rate=1e-3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "69537480",
   "metadata": {},
   "source": [
    "下面在循环神经网络的基础上实现多层循环神经网络。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "6eb2e0ed",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "epoch-199, loss=0.2808: 100%|█| 200/200 [04:08<00:00,  1.24s\n"
     ]
    },
    {
     "data": {
      "image/png": "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TSYTL774ouscb76PZ/L5cCa/Q9PS0rjssssIDAwkNjaWRx99FJvN1mB1Kqj8yieffML06dN56qmn2LBhA3369GHcuHFkZWV5urSzsmTJEqZOncqqVauYP38+VVVVXHrppZSUlLidd9ddd5GRkeH6euGFFzxUcf316NHDrfbly5e7nnvooYf45ptv+Oyzz1iyZAlHjhzhmmuu8WC19bd27Vq365s/fz4A1113neuc5nb/SkpK6NOnD7Nnz67z+RdeeIFXXnmF1157jdWrVxMUFMS4ceMoLy93nTNlyhS2b9/O/Pnz+fbbb1m6dCl33313U13CKZ3q+kpLS9mwYQNPPPEEGzZs4IsvvmD37t1ceeWVJ5z7pz/9ye2+3n///U1R/hk53T0EGD9+vFv9H3/8sdvz3nwP4fTXWPvaMjIyeOeddzCZTFx77bVu53nrfTyTz4fT/Q612+1cdtllVFZWsmLFCt5//33ee+89nnzyyYYr1BA3gwcPNqZOnep6bLfbjVatWhkzZ870YFUNJysrywCMJUuWuI6NGjXKeOCBBzxX1Dl46qmnjD59+tT5XH5+vuHr62t89tlnrmM7d+40AGPlypVNVGHDe+CBB4wOHToYDofDMIzmff8MwzAA48svv3Q9djgcRnx8vPHiiy+6juXn5xtWq9X4+OOPDcMwjB07dhiAsXbtWtc58+bNM0wmk3H48OEmq/1M/Pr66rJmzRoDMFJTU13H2rZta7z88suNW1wDqesab731VmPSpEknfU1zuoeGcWb3cdKkScbFF1/sdqw53cdffz6cye/Q77//3jCbzUZmZqbrnFdffdUIDQ01KioqGqQutajUUllZyfr16xk7dqzrmNlsZuzYsaxcudKDlTWcgoICACIjI92O/+c//yE6OpqePXsyY8YMSktLPVHeWdm7dy+tWrWiffv2TJkyhbS0NADWr19PVVWV2/3s2rUrSUlJzfZ+VlZW8uGHH/Lb3/7WbSPO5nz/fi0lJYXMzEy3+xYWFsaQIUNc923lypWEh4czcOBA1zljx47FbDazevXqJq/5XBUUFGAymQgPD3c7/vzzzxMVFUW/fv148cUXG7Q5vSksXryY2NhYunTpwr333ktOTo7ruZZ2D48ePcp3333HHXfcccJzzeU+/vrz4Ux+h65cuZJevXq5LdI6btw4CgsL2b59e4PU5fGVab1JdnY2drv9hFVx4+Li2LVrl4eqajgOh4MHH3yQESNG0LNnT9fxm266ibZt29KqVSu2bNnCY489xu7du/niiy88WO2ZGTJkCO+99x5dunQhIyODZ555hgsvvJBt27aRmZmJn5/fCb/84+LiyMzM9EzB52ju3Lnk5+dz2223uY415/tXl5p7U9e/w5rnMjMziY2NdXvex8eHyMjIZndvy8vLeeyxx5g8ebLbZm/Tpk2jf//+REZGsmLFCmbMmEFGRgYvvfSSB6s9c+PHj+eaa66hXbt27N+/n//5n/9hwoQJrFy5EovF0qLuIcD7779PSEjICV3LzeU+1vX5cCa/QzMzM+v8t1rzXENQUDmPTJ06lW3btrmN4QDc+oR79epFQkICY8aMYf/+/XTo0KGpy6yXCRMmuL7v3bs3Q4YMoW3btnz66acEBAR4sLLG8fbbbzNhwgS3rdGb8/0731VVVXH99ddjGAavvvqq23PTp093fd+7d2/8/Pz43e9+x8yZM5vFUu033nij6/tevXrRu3dvOnTowOLFixkzZowHK2sc77zzDlOmTMHf39/teHO5jyf7fPAG6vqpJTo6GovFcsKI5qNHjxIfH++hqhrGfffdx7fffsuiRYto06bNKc8dMmQIAPv27WuK0hpUeHg4nTt3Zt++fcTHx1NZWUl+fr7bOc31fqamprJgwQLuvPPOU57XnO8f4Lo3p/p3GB8ff8IAd5vNRm5ubrO5tzUhJTU1lfnz57u1ptRlyJAh2Gw2Dh482DQFNrD27dsTHR3t+nvZEu5hjWXLlrF79+7T/tsE77yPJ/t8OJPfofHx8XX+W615riEoqNTi5+fHgAEDWLhwoeuYw+Fg4cKFDBs2zIOVnT3DMLjvvvv48ssv+fnnn2nXrt1pX7Np0yYAEhISGrm6hldcXMz+/ftJSEhgwIAB+Pr6ut3P3bt3k5aW1izv57vvvktsbCyXXXbZKc9rzvcPoF27dsTHx7vdt8LCQlavXu26b8OGDSM/P5/169e7zvn5559xOByuoObNakLK3r17WbBgAVFRUad9zaZNmzCbzSd0lzQXhw4dIicnx/X3srnfw9refvttBgwYQJ8+fU57rjfdx9N9PpzJ79Bhw4axdetWt9BZE7y7d+/eYIVKLXPmzDGsVqvx3nvvGTt27DDuvvtuIzw83G1Ec3Ny7733GmFhYcbixYuNjIwM11dpaalhGIaxb98+409/+pOxbt06IyUlxfjqq6+M9u3bGyNHjvRw5Wfm4YcfNhYvXmykpKQYv/zyizF27FgjOjrayMrKMgzDMO655x4jKSnJ+Pnnn41169YZw4YNM4YNG+bhquvPbrcbSUlJxmOPPeZ2vLnev6KiImPjxo3Gxo0bDcB46aWXjI0bN7pmvTz//PNGeHi48dVXXxlbtmwxJk2aZLRr184oKytzvcf48eONfv36GatXrzaWL19udOrUyZg8ebKnLsnNqa6vsrLSuPLKK402bdoYmzZtcvt3WTNLYsWKFcbLL79sbNq0ydi/f7/x4YcfGjExMcYtt9zi4Ss77lTXWFRUZDzyyCPGypUrjZSUFGPBggVG//79jU6dOhnl5eWu9/Dme2gYp/97ahiGUVBQYAQGBhqvvvrqCa/39vt4us8Hwzj971CbzWb07NnTuPTSS41NmzYZP/zwgxETE2PMmDGjwepUUKnDP//5TyMpKcnw8/MzBg8ebKxatcrTJZ01oM6vd9991zAMw0hLSzNGjhxpREZGGlar1ejYsaPx6KOPGgUFBZ4t/AzdcMMNRkJCguHn52e0bt3auOGGG4x9+/a5ni8rKzN+//vfGxEREUZgYKBx9dVXGxkZGR6s+Oz8+OOPBmDs3r3b7XhzvX+LFi2q8+/lrbfeahiGc4ryE088YcTFxRlWq9UYM2bMCdeek5NjTJ482QgODjZCQ0ON22+/3SgqKvLA1ZzoVNeXkpJy0n+XixYtMgzDMNavX28MGTLECAsLM/z9/Y1u3boZzz33nNuHvKed6hpLS0uNSy+91IiJiTF8fX2Ntm3bGnfdddcJ/8PnzffQME7/99QwDOP11183AgICjPz8/BNe7+338XSfD4ZxZr9DDx48aEyYMMEICAgwoqOjjYcfftioqqpqsDpN1cWKiIiIeB2NURERERGvpaAiIiIiXktBRURERLyWgoqIiIh4LQUVERER8VoKKiIiIuK1FFRERETEaymoiIiIiNdSUBGRM5KcnMzf//73Mz5/8eLFmEymEzY0a6nq+/MRkTPj4+kCRKRxjB49mr59+zbYh+fatWsJCgo64/OHDx9ORkYGYWFhDfLni8j5SUFF5DxmGAZ2ux0fn9P/KoiJianXe/v5+TXYNu8icv5S149IC3TbbbexZMkS/vGPf2AymTCZTBw8eNDVHTNv3jwGDBiA1Wpl+fLl7N+/n0mTJhEXF0dwcDCDBg1iwYIFbu/5664Nk8nEW2+9xdVXX01gYCCdOnXi66+/dj3/666f9957j/DwcH788Ue6detGcHAw48ePJyMjw/Uam83GtGnTCA8PJyoqiscee4xbb72Vq6666pTXu3z5ci688EICAgJITExk2rRplJSUuNX+7LPPMnnyZIKCgmjdujWzZ892e4+0tDQmTZpEcHAwoaGhXH/99Rw9etTtnG+++YZBgwbh7+9PdHQ0V199tdvzpaWl/Pa3vyUkJISkpCTeeOONU9YtIqenoCLSAv3jH/9g2LBh3HXXXWRkZJCRkUFiYqLr+ccff5znn3+enTt30rt3b4qLi5k4cSILFy5k48aNjB8/niuuuIK0tLRT/jnPPPMM119/PVu2bGHixIlMmTKF3Nzck55fWlrKX//6V/7973+zdOlS0tLSeOSRR1zP/9///R//+c9/ePfdd/nll18oLCxk7ty5p6xh//79jB8/nmuvvZYtW7bwySefsHz5cu677z6381588UX69OnDxo0befzxx3nggQeYP38+AA6Hg0mTJpGbm8uSJUuYP38+Bw4c4IYbbnC9/rvvvuPqq69m4sSJbNy4kYULFzJ48GC3P+Nvf/sbAwcOZOPGjfz+97/n3nvvZffu3aesX0ROo8H2YRYRrzJq1CjjgQcecDtWs2393LlzT/v6Hj16GP/85z9dj9u2bWu8/PLLrseA8cc//tH1uLi42ACMefPmuf1ZeXl5hmEYxrvvvmsAxr59+1yvmT17thEXF+d6HBcXZ7z44ouuxzabzUhKSjImTZp00jrvuOMO4+6773Y7tmzZMsNsNhtlZWWu2sePH+92zg033GBMmDDBMAzD+OmnnwyLxWKkpaW5nt++fbsBGGvWrDEMwzCGDRtmTJky5aR1tG3b1rj55ptdjx0OhxEbG2u8+uqrJ32NiJyeWlREzkMDBw50e1xcXMwjjzxCt27dCA8PJzg4mJ07d562RaV3796u74OCgggNDSUrK+uk5wcGBtKhQwfX44SEBNf5BQUFHD161K2VwmKxMGDAgFPWsHnzZt577z2Cg4NdX+PGjcPhcJCSkuI6b9iwYW6vGzZsGDt37gRg586dJCYmurU6de/enfDwcNc5mzZtYsyYMaespfbPw2QyER8ff8qfh4icngbTipyHfj1755FHHmH+/Pn89a9/pWPHjgQEBPCb3/yGysrKU76Pr6+v22OTyYTD4ajX+YZh1LN6d8XFxfzud79j2rRpJzyXlJR0Tu9dW0BAwGnPqe/PQ0ROTy0qIi2Un58fdrv9jM795ZdfuO2227j66qvp1asX8fHxHDx4sHEL/JWwsDDi4uJYu3at65jdbmfDhg2nfF3//v3ZsWMHHTt2POHLz8/Pdd6qVavcXrdq1Sq6desGQLdu3UhPTyc9Pd31/I4dO8jPz6d79+6As7Vk4cKF53ydIlI/alERaaGSk5NZvXo1Bw8eJDg4mMjIyJOe26lTJ7744guuuOIKTCYTTzzxhEdaAu6//35mzpxJx44d6dq1K//85z/Jy8vDZDKd9DWPPfYYQ4cO5b777uPOO+8kKCiIHTt2MH/+fGbNmuU675dffuGFF17gqquuYv78+Xz22Wd89913AIwdO5ZevXoxZcoU/v73v2Oz2fj973/PqFGjXN1kTz31FGPGjKFDhw7ceOON2Gw2vv/+ex577LHG/aGInOfUoiLSQj3yyCNYLBa6d+9OTEzMKcebvPTSS0RERDB8+HCuuOIKxo0bR//+/ZuwWqfHHnuMyZMnc8sttzBs2DDXeBN/f/+TvqZ3794sWbKEPXv2cOGFF9KvXz+efPJJWrVq5Xbeww8/zLp16+jXrx9//vOfeemllxg3bhzg7KL56quviIiIYOTIkYwdO5b27dvzySefuF4/evRoPvvsM77++mv69u3LxRdfzJo1axrnByEiLibjXDuIRUQaicPhoFu3blx//fU8++yzZ/0+ycnJPPjggzz44IMNV5yINAl1/YiI10hNTeWnn35i1KhRVFRUMGvWLFJSUrjppps8XZqIeIi6fkTEa5jNZt577z0GDRrEiBEj2Lp1KwsWLHANehWR84+6fkRERMRrqUVFREREvJaCioiIiHgtBRURERHxWgoqIiIi4rUUVERERMRrKaiIiIiI11JQEREREa+loCIiIiJe6/8D/R0iKhIpqWEAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\"\"\"\n",
    "部分代码参考了GitHub项目d2l-ai/d2l-zh的思路\n",
    "（Copyright (c) 2022 Aston Zhang, Zachary C. Lipton,\n",
    "Mu Li, and Alexander J. Smola, Apache-2.0 License（见附录））\n",
    "\"\"\"\n",
    "# 多层循环神经网络\n",
    "class DeepRNN(nn.Module):\n",
    "    def __init__(self, input_size, hidden_size, num_layers, dropout=0.):\n",
    "        super(DeepRNN, self).__init__()\n",
    "        self.input_size = input_size\n",
    "        self.hidden_size = hidden_size\n",
    "        self.num_layers = num_layers\n",
    "        self._flat_weight_names = []\n",
    "        self._all_weights = []\n",
    "        self.drop = nn.Dropout(p=dropout)\n",
    "        # 定义每一层循环神经网络的参数，由于参数数量不固定，\n",
    "        # 因此使用统一的命名方法更方便调用和管理\n",
    "        for layer in range(num_layers):\n",
    "            W_xh = nn.Parameter(normal((input_size, hidden_size)))\n",
    "            W_hh = nn.Parameter(normal((hidden_size, hidden_size)))\n",
    "            b_h = nn.Parameter(torch.zeros(hidden_size))\n",
    "            layer_params = (W_xh, W_hh, b_h)\n",
    "            params_names = [f'W_xh_l{layer}', f'W_hh_l{layer}', \\\n",
    "                f'b_h_l{layer}']\n",
    "            \n",
    "            # 将新的参数加入到成员列表中\n",
    "            for name, param in zip(params_names, layer_params):\n",
    "                setattr(self, name, param)\n",
    "            self._flat_weight_names.extend(params_names)\n",
    "            self._all_weights.append(params_names)\n",
    "            input_size = hidden_size\n",
    "        self._flat_weights = [getattr(self, wn) if hasattr(self, wn) \\\n",
    "            else None for wn in self._flat_weight_names]\n",
    "    \n",
    "    def __setattr__(self, attr, value):\n",
    "        if hasattr(self, '_flat_weight_names') and \\\n",
    "            attr in self._flat_weight_names:\n",
    "            idx = self._flat_weight_names.index(attr)\n",
    "            self._flat_weights[idx] = value\n",
    "        super().__setattr__(attr, value)\n",
    "    \n",
    "    def init_rnn_state(self, batch_size, hidden_size):\n",
    "        return (torch.zeros((self.num_layers, batch_size, hidden_size), \n",
    "            dtype=torch.float),)\n",
    "    \n",
    "    def forward(self, inputs, states):\n",
    "        seq_len, batch_size, _ = inputs.shape\n",
    "        layer_hidden_states, = states\n",
    "        layer_h_t = []\n",
    "        input_states = inputs\n",
    "        # 需要保存每一层的输出作为下一层的输入\n",
    "        for layer in range(self.num_layers):\n",
    "            hiddens = []\n",
    "            hidden_state = layer_hidden_states[layer]\n",
    "            for step in range(seq_len):\n",
    "                xh = torch.mm(input_states[step], \n",
    "                    getattr(self, f'W_xh_l{layer}'))\n",
    "                hh = torch.mm(hidden_state, getattr(self, f'W_hh_l{layer}'))\n",
    "                hidden_state = xh + hh + getattr(self, f'b_h_l{layer}')\n",
    "                hidden_state = self.drop(torch.tanh(hidden_state))\n",
    "                hiddens.append(hidden_state)\n",
    "            input_states = torch.stack(hiddens, dim=0)\n",
    "            layer_h_t.append(hidden_state)\n",
    "        return input_states, torch.stack(layer_h_t, dim=0)\n",
    "\n",
    "data_loader = DataLoader(torch.tensor(sent_tokens, dtype=torch.long), \n",
    "    batch_size=16, shuffle=True)\n",
    "deep_rnn = DeepRNN(128, 128, 2)\n",
    "train_rnn_lm(data_loader, deep_rnn, vocab_size, hidden_size=128, \n",
    "    epochs=200, learning_rate=1e-3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f0f1be39",
   "metadata": {},
   "source": [
    "\n",
    "\n",
    "需要注意的是，双向循环神经网络在每个位置的输出同时包含了来自左边和右边的信息，也就是整个输入序列的信息。所以双向循环神经网络并不能用于语言模型，因为语言模型需要仅根据序列中每个词左边的信息来预测这个词。\n",
    "\n",
    "下面的双向循环神经网络是一个简单的示例，要求一次只能输入一个序列。如果想在一个批次中并行处理不同长度的输入序列以获得更高的运行效率，可以通过填充将不同长度的输入对齐。单向循环神经网络的填充较为简单，只需在每个序列末尾添加字符就可以。但是双向循环神经网络的填充更加复杂，正向和反向循环神经网络的读取顺序相反，难以保证两个方向的循环神经网络都填充在末尾，实现起来较为困难。\n",
    "解决方案参考PyTorch中的pack_padded_sequence和pad_packed_sequence。双向循环神经网络不能用于训练语言模型，因此不再提供训练示例代码。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "0344d588",
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "部分代码参考了GitHub项目d2l-ai/d2l-zh的思路\n",
    "（Copyright (c) 2022 Aston Zhang, Zachary C. Lipton,\n",
    "Mu Li, and Alexander J. Smola, Apache-2.0 License（见附录））\n",
    "\"\"\"\n",
    "# 双向循环神经网络\n",
    "class BiRNN(nn.Module):\n",
    "    def __init__(self, input_size, hidden_size):\n",
    "        super(BiRNN, self).__init__()\n",
    "        self.input_size = input_size\n",
    "        self.hidden_size = hidden_size\n",
    "        # 正向循环神经网络参数\n",
    "        self.W_xh = nn.Parameter(normal((input_size, hidden_size)))\n",
    "        self.W_hh = nn.Parameter(normal((hidden_size, hidden_size)))\n",
    "        self.b_h = nn.Parameter(torch.zeros(hidden_size))\n",
    "        # 反向循环神经网络参数\n",
    "        self.W_xh_reverse = nn.Parameter(normal((input_size, hidden_size)))\n",
    "        self.W_hh_reverse = nn.Parameter(normal((hidden_size, hidden_size)))\n",
    "        self.b_h_reverse = nn.Parameter(torch.zeros(hidden_size))\n",
    "        \n",
    "    # 分别为正向和反向循环神经网络准备初始状态\n",
    "    def init_rnn_state(self, batch_size, hidden_size):\n",
    "        return (torch.zeros((batch_size, hidden_size), dtype=torch.float),\n",
    "               torch.zeros((batch_size, hidden_size), dtype=torch.float))\n",
    "    \n",
    "    def forward(self, inputs, states):\n",
    "        seq_len, batch_size, _ = inputs.shape\n",
    "        hidden_state, reverse_hidden_state = states\n",
    "        hiddens = []\n",
    "        for step in range(seq_len):\n",
    "            xh = torch.mm(inputs[step], self.W_xh)\n",
    "            hh = torch.mm(hidden_state, self.W_hh)\n",
    "            hidden_state = xh + hh + self.b_h\n",
    "            hidden_state = torch.tanh(hidden_state)\n",
    "            hiddens.append(hidden_state)\n",
    "        reverse_hiddens = []\n",
    "        for step in range(seq_len-1, -1, -1):\n",
    "            xh = torch.mm(inputs[step], self.W_xh_reverse)\n",
    "            hh = torch.mm(reverse_hidden_state, self.W_hh_reverse)\n",
    "            reverse_hidden_state = xh + hh + self.b_h_reverse\n",
    "            reverse_hidden_state = torch.tanh(reverse_hidden_state)\n",
    "            reverse_hiddens.insert(0, reverse_hidden_state)\n",
    "        # 将正向和反向循环神经网络输出的隐状态拼接在一起\n",
    "        combined_hiddens = []\n",
    "        for h1, h2 in zip(hiddens, reverse_hiddens):\n",
    "            combined_hiddens.append(torch.cat([h1, h2], dim=-1))\n",
    "        return torch.stack(combined_hiddens, dim=0), ()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b79ef2c6",
   "metadata": {},
   "source": [
    "下面实现一个带有缩放点乘注意力的循环神经网络，并用其训练语言模型。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "b5c32275",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "epoch-199, loss=0.9612: 100%|█| 200/200 [05:39<00:00,  1.70s\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\"\"\"\n",
    "部分代码参考了GitHub项目d2l-ai/d2l-zh的思路\n",
    "（Copyright (c) 2022 Aston Zhang, Zachary C. Lipton,\n",
    "Mu Li, and Alexander J. Smola, Apache-2.0 License（见附录））\n",
    "\"\"\"\n",
    "class AttentionRNN(nn.Module):\n",
    "    def __init__(self, input_size, hidden_size):\n",
    "        super(AttentionRNN, self).__init__()\n",
    "        self.input_size = input_size\n",
    "        self.hidden_size = hidden_size\n",
    "        # 循环神经网络参数\n",
    "        self.W_xh = nn.Parameter(normal((input_size, hidden_size)))\n",
    "        self.W_hh = nn.Parameter(normal((hidden_size, hidden_size)))\n",
    "        self.b_h = nn.Parameter(torch.zeros(hidden_size))\n",
    "    \n",
    "    def init_rnn_state(self, batch_size, hidden_size):\n",
    "        return (torch.zeros((batch_size, hidden_size),\\\n",
    "            dtype=torch.float),)\n",
    "    \n",
    "    # 缩放点乘注意力\n",
    "    def attention(self, query, keys, values):\n",
    "        \"\"\"\n",
    "        query: batch_size * hidden_size\n",
    "        keys/values: batch_size * prev_len * hidden_size\n",
    "        \"\"\"\n",
    "        # batch_size * 1 * hidden_size\n",
    "        query = torch.unsqueeze(query, 1)\n",
    "        # batch_size * hidden_size * prev_len\n",
    "        keys = torch.permute(keys, (0, 2, 1))\n",
    "        # batch_size * 1 * prev_len\n",
    "        attention_scores = torch.bmm(query, keys) / np.sqrt(\\\n",
    "            self.hidden_size)\n",
    "        # batch_size * 1 * prev_len\n",
    "        attention_weights = F.softmax(attention_scores, dim=1)\n",
    "        # batch_size * hidden_size\n",
    "        attention_state = torch.squeeze(torch.bmm(attention_weights,\\\n",
    "            values))\n",
    "        return attention_state\n",
    "\n",
    "    def forward(self, inputs, states):\n",
    "        seq_len, batch_size, _ = inputs.shape\n",
    "        hidden_state, = states\n",
    "        hiddens = []\n",
    "        attention_hiddens = []\n",
    "        for step in range(seq_len):\n",
    "            xh = torch.mm(inputs[step], self.W_xh)\n",
    "            hh = torch.mm(hidden_state, self.W_hh)\n",
    "            hidden_state = xh + hh + self.b_h\n",
    "            hidden_state = torch.tanh(hidden_state)\n",
    "            \n",
    "            if step > 0:\n",
    "                # batch_size * hidden_size\n",
    "                query = hidden_state\n",
    "                # batch_size * prev_len * hidden_size\n",
    "                keys = values = torch.permute(torch.stack(hiddens,\\\n",
    "                    dim=0), (1, 0, 2))\n",
    "                \n",
    "                attention_state = self.attention(query, keys, values)                \n",
    "                attention_hiddens.append(attention_state)\n",
    "            else:\n",
    "                # 第0步，历史隐状态为空，无法进行注意力运算，\n",
    "                # 直接用隐状态填充\n",
    "                attention_hiddens.append(hidden_state)\n",
    "                \n",
    "            hiddens.append(hidden_state)\n",
    "        return torch.stack(attention_hiddens, dim=0), \\\n",
    "            (attention_state,)\n",
    "    \n",
    "data_loader = DataLoader(torch.tensor(sent_tokens, dtype=torch.long), \n",
    "    batch_size=16, shuffle=True)\n",
    "\n",
    "attention_rnn = AttentionRNN(128, 128)\n",
    "train_rnn_lm(data_loader, attention_rnn, vocab_size, hidden_size=128, \n",
    "    epochs=200, learning_rate=1e-3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c95d2f4b",
   "metadata": {},
   "source": [
    "下面是多头注意力的代码实现。我们在实现AttentionRNN时将注意力计算封装在成员函数里面，因此实现多头注意力时可以直接继承AttentionRNN类，只用改写构造函数和attention()成员方法即可。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "6373e7ab",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "epoch-199, loss=1.2390: 100%|█| 200/200 [15:38<00:00,  4.69s\n"
     ]
    },
    {
     "data": {
      "image/png": "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IgpZDCpEREQUshhUiIiIKGQxqBAREVHIYlAhIiKikMWgQkRERCGLQYWIuiUzMxMvvvhit6/ftm0bBEFod6DZUNXT3x8i6h5NsAdARP1j0aJFmDZtWp/98Ny/fz/Cw8O7ff38+fNRWloKs9ncJ69PRMMTgwrRMCaKIlwuFzSarv8piIuL69Fz63S6PjvmnYiGL079EA1Bd999N7Zv346XXnoJgiBAEATk5eUp0zEbNmzAzJkzodfrsXPnTpw/fx433ngjEhISEBERgdmzZ2Pz5s1+z9l2akMQBPzlL3/BzTffjLCwMIwePRqffvqpcn/bqZ/169fDYrHgyy+/xPjx4xEREYFly5ahtLRUeYzT6cTq1athsVgQExODJ554AnfddRduuummTt/vzp07cdlll8FoNCItLQ2rV69GU1OT39h//etfY8WKFQgPD0dKSgpeffVVv+coKCjAjTfeiIiICJhMJtx+++0oLy/3u+bf//43Zs+eDYPBgNjYWNx8881+99tsNtx7772IjIxEeno6/vznP3c6biLqGoMK0RD00ksvYd68efjRj36E0tJSlJaWIi0tTbn/P//zP/Hss8/i9OnTmDJlChobG3Httdfi66+/xuHDh7Fs2TIsX74cBQUFnb7O008/jdtvvx3Hjh3Dtddei5UrV6KmpqbD6202G/7whz/g73//O3bs2IGCggI8/vjjyv2/+93v8NZbb+GNN97At99+i/r6enz88cedjuH8+fNYtmwZbr31Vhw7dgzvvfcedu7ciQcffNDvuueeew5Tp07F4cOH8Z//+Z94+OGHsWnTJgCA2+3GjTfeiJqaGmzfvh2bNm3ChQsXcMcddyiP//zzz3HzzTfj2muvxeHDh/H1119jzpw5fq/xP//zP5g1axYOHz6Mn/zkJ3jggQeQnZ3d6fiJqAt9dg4zEYWUhQsXig8//LDfbfKx9R9//HGXj584caL48ssvK99nZGSIL7zwgvI9APG///u/le8bGxtFAOKGDRv8Xqu2tlYURVF84403RABiTk6O8phXX31VTEhIUL5PSEgQn3vuOeV7p9MppqenizfeeGOH4/zBD34g3nfffX63ffPNN6JKpRKbm5uVsS9btszvmjvuuEO85pprRFEUxa+++kpUq9ViQUGBcv/JkydFAOK+fftEURTFefPmiStXruxwHBkZGeJ3v/td5Xu32y3Gx8eL69at6/AxRNQ1VlSIhqFZs2b5fd/Y2IjHH38c48ePh8ViQUREBE6fPt1lRWXKlCnKr8PDw2EymVBRUdHh9WFhYRg1apTyfVJSknK91WpFeXm5X5VCrVZj5syZnY7h6NGjWL9+PSIiIpSvpUuXwu12Izc3V7lu3rx5fo+bN28eTp8+DQA4ffo00tLS/KpOEyZMgMViUa45cuQIFi9e3OlYfH8/BEFAYmJip78fRNQ1NtMSDUNtV+88/vjj2LRpE/7whz8gKysLRqMR//Ef/4GWlpZOn0er1fp9LwgC3G53j64XRbGHo/fX2NiIH//4x1i9enW7+9LT0y/quX0ZjcYur+np7wcRdY0VFaIhSqfTweVydevab7/9FnfffTduvvlmTJ48GYmJicjLy+vfAbZhNpuRkJCA/fv3K7e5XC4cOnSo08fNmDEDp06dQlZWVrsvnU6nXLdnzx6/x+3Zswfjx48HAIwfPx6FhYUoLCxU7j916hTq6uowYcIEAFK15Ouvv77o90lEPcOKCtEQlZmZib179yIvLw8RERGIjo7u8NrRo0fjww8/xPLlyyEIAn7xi18EpRLw0EMPYe3atcjKysK4cePw8ssvo7a2FoIgdPiYJ554ApdccgkefPBB/PCHP0R4eDhOnTqFTZs24ZVXXlGu+/bbb/H73/8eN910EzZt2oT3338fn3/+OQBgyZIlmDx5MlauXIkXX3wRTqcTP/nJT7Bw4UJlmuzJJ5/E4sWLMWrUKNx5551wOp344osv8MQTT/TvbwrRMMeKCtEQ9fjjj0OtVmPChAmIi4vrtN/k+eefR1RUFObPn4/ly5dj6dKlmDFjxgCOVvLEE09gxYoV+P73v4958+Yp/SYGg6HDx0yZMgXbt2/H2bNncdlll2H69On45S9/ieTkZL/rHnvsMRw4cADTp0/Hb37zGzz//PNYunQpAGmK5pNPPkFUVBQuv/xyLFmyBCNHjsR7772nPH7RokV4//338emnn2LatGm48sorsW/fvv75jSAihSBe7AQxEVE/cbvdGD9+PG6//Xb8+te/7vXzZGZm4pFHHsEjjzzSd4MjogHBqR8iChn5+fn46quvsHDhQjgcDrzyyivIzc3Fd77znWAPjYiChFM/RBQyVCoV1q9fj9mzZ2PBggU4fvw4Nm/erDS9EtHww6kfIiIiClmsqBAREVHIYlAhIiKikMWgQkRERCGLQYWIiIhCFoMKERERhSwGFSIiIgpZDCpEREQUshhUiIiIKGT9f2ylTdNQeUuiAAAAAElFTkSuQmCC",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "\"\"\"\n",
    "部分代码参考了GitHub项目d2l-ai/d2l-zh的思路\n",
    "（Copyright (c) 2022 Aston Zhang, Zachary C. Lipton,\n",
    "Mu Li, and Alexander J. Smola, Apache-2.0 License（见附录））\n",
    "\"\"\"\n",
    "# 多头注意力循环神经网络\n",
    "class MultiHeadAttentionRNN(AttentionRNN):\n",
    "    def __init__(self, input_size, hidden_size, num_heads=4):\n",
    "        super().__init__(input_size, hidden_size)\n",
    "        # 简单起见，一般要求hidden_size能够被num_heads整除\n",
    "        assert hidden_size % num_heads == 0\n",
    "        self.num_heads = num_heads\n",
    "        # 多头注意力参数，用于将查询、键、值映射到子空间\n",
    "        self.W_aq = nn.Parameter(normal((hidden_size, hidden_size)))\n",
    "        self.b_aq = nn.Parameter(torch.zeros(hidden_size))\n",
    "        self.W_ak = nn.Parameter(normal((hidden_size, hidden_size)))\n",
    "        self.b_ak = nn.Parameter(torch.zeros(hidden_size))\n",
    "        self.W_av = nn.Parameter(normal((hidden_size, hidden_size)))\n",
    "        self.b_av = nn.Parameter(torch.zeros(hidden_size))\n",
    "        self.W_ac = nn.Parameter(normal((hidden_size, hidden_size)))\n",
    "        self.b_ac = nn.Parameter(torch.zeros(hidden_size))\n",
    "\n",
    "    # 多头缩放点乘注意力\n",
    "    def attention(self, query, keys, values):\n",
    "        \"\"\"\n",
    "        query: batch_size * hidden_size\n",
    "        keys/values: batch_size * prev_len * hidden_size\n",
    "        \"\"\"\n",
    "        query = torch.mm(query, self.W_aq) + self.b_aq\n",
    "        ori_shape = keys.size()\n",
    "        \n",
    "        keys = torch.reshape(torch.mm(torch.flatten(keys, \n",
    "                start_dim=0, end_dim=1), self.W_ak) + \n",
    "                self.b_ak, ori_shape)\n",
    "        values = torch.reshape(torch.mm(torch.flatten(values, \n",
    "                start_dim=0, end_dim=1), self.W_av) + \n",
    "                self.b_av, ori_shape)\n",
    "        # batch_size * 1 * hidden_size\n",
    "        query = torch.unsqueeze(query, 1)\n",
    "        # batch_size * hidden_size * prev_len\n",
    "        keys = torch.permute(keys, (0, 2, 1))\n",
    "        \n",
    "        head_size = self.hidden_size // self.num_heads\n",
    "        query = torch.split(query, head_size, 2)\n",
    "        keys = torch.split(keys, head_size, 1)\n",
    "        values = torch.split(values, head_size, 2)\n",
    "        \n",
    "        heads = []\n",
    "        for i in range(self.num_heads):\n",
    "            # batch_size * 1 * prev_len\n",
    "            head_scores = torch.bmm(query[i], keys[i]) / np.sqrt(\n",
    "                self.hidden_size // self.num_heads) \n",
    "            # batch_size * 1 * prev_len\n",
    "            head_weights = F.softmax(head_scores, dim=1)\n",
    "            # batch_size * head_size\n",
    "            head_state = torch.squeeze(torch.bmm(head_weights, \n",
    "                values[i])) \n",
    "            heads.append(head_state)\n",
    "        heads = torch.cat(heads, dim=1)        \n",
    "        attention_state = torch.mm(heads, self.W_ac) + self.b_ac\n",
    "\n",
    "        return attention_state\n",
    "\n",
    "data_loader = DataLoader(torch.tensor(sent_tokens, \n",
    "    dtype=torch.long), batch_size=16, shuffle=True)\n",
    "\n",
    "mha_rnn = MultiHeadAttentionRNN(128, 128)\n",
    "train_rnn_lm(data_loader, mha_rnn, vocab_size, hidden_size=128, \n",
    "    epochs=200, learning_rate=1e-3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "166d4dce",
   "metadata": {},
   "source": [
    "下面来实现Transformer模型，包括加入了位置编码的嵌入层、缩放点乘注意力、多头注意力、层归一化等具体实现。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "0e4110a4",
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "代码修改自GitHub项目huggingface/transformers\n",
    "（Copyright (c) 2020, The HuggingFace Team, Apache-2.0 License（见附录））\n",
    "\"\"\"\n",
    "# 实现Transformer模型\n",
    "class EmbeddingLayer(nn.Module):\n",
    "    def __init__(self, vocab_size, max_len, embed_size):\n",
    "        super().__init__()\n",
    "        self.vocab_size = vocab_size\n",
    "        self.max_len = max_len\n",
    "        self.embed_size = embed_size\n",
    "        self.word_embedding = nn.Embedding(vocab_size, embed_size)\n",
    "        self.pos_embedding = nn.Embedding(max_len, embed_size)\n",
    "        \n",
    "    def forward(self, input_ids, pos_ids):\n",
    "        \"\"\"\n",
    "        input_ids/pos_ids: batch_size * seq_len\n",
    "        return: batch_size * seq_len * embed_size\n",
    "        \"\"\"\n",
    "        word_embed = self.word_embedding(input_ids)\n",
    "        pos_embed = self.pos_embedding(pos_ids)\n",
    "        # 将词嵌入和位置嵌入相加得到嵌入层输出\n",
    "        return word_embed + pos_embed\n",
    "\n",
    "# 缩放点乘注意力\n",
    "class ScaledDotProductAttention(nn.Module):\n",
    "    def __init__(self, dropout):\n",
    "        super().__init__()\n",
    "        self.dropout = nn.Dropout(dropout)\n",
    "    \n",
    "    def forward(self, queries, keys, values, attention_mask):\n",
    "        \"\"\"\n",
    "        queries/keys/values: batch_size * seq_len * hidden_size\n",
    "        attention_mask: batch_size * seq_len * seq_len\n",
    "        return: batch_size * seq_len * hidden_size\n",
    "        \"\"\"\n",
    "        d = queries.size(-1)\n",
    "        # 根据点乘注意力的矩阵形式计算注意力分数，除以查询向量或键向量\n",
    "        # 维度的平方根，即为缩放点乘注意力\n",
    "        scores = torch.bmm(queries, torch.transpose(keys, 1, 2)) / np.sqrt(d)\n",
    "        # 将掩码为0的位置的注意力分数设为一个大负数，根据softmax函数\n",
    "        # 的性质，这些注意力分数归一化后接近0\n",
    "        scores[attention_mask == 0] = -1e6\n",
    "        self.attention_weights = F.softmax(scores, dim=-1)\n",
    "        return torch.bmm(self.dropout(self.attention_weights), values)\n",
    "    \n",
    "class MultiHeadSelfAttention(nn.Module):\n",
    "    def __init__(self, hidden_size, num_heads, dropout):\n",
    "        super().__init__()\n",
    "        assert hidden_size % num_heads == 0\n",
    "        self.hidden_size = hidden_size\n",
    "        self.num_heads = num_heads\n",
    "        self.W_q = nn.Linear(hidden_size, hidden_size)\n",
    "        self.W_k = nn.Linear(hidden_size, hidden_size)\n",
    "        self.W_v = nn.Linear(hidden_size, hidden_size)\n",
    "        self.W_o = nn.Linear(hidden_size, hidden_size)\n",
    "        self.attention = ScaledDotProductAttention(dropout)\n",
    "    \n",
    "    def transpose_qkv(self, states):\n",
    "        # 将长度为hidden_size的向量分成num_heads个长度相等的向量\n",
    "        states = states.reshape(states.shape[0], states.shape[1],\\\n",
    "            self.num_heads, self.hidden_size // self.num_heads)\n",
    "        states = torch.permute(states, (0, 2, 1, 3))\n",
    "        return states.reshape(-1, states.shape[2], states.shape[3])\n",
    "    \n",
    "    # 与transpose_qkv的变换相反\n",
    "    def transpose_output(self, states):\n",
    "        states = states.reshape(-1, self.num_heads, states.shape[1],\\\n",
    "            states.shape[2])\n",
    "        states = torch.permute(states, (0, 2, 1, 3))\n",
    "        return states.reshape(states.shape[0], states.shape[1], -1)\n",
    "    \n",
    "    def forward(self, queries, keys, values, attention_mask):\n",
    "        \"\"\"\n",
    "        querys/keys/values: batch * seq_len * hidden_size\n",
    "        attention_mask: batch * seq_len * seq_len\n",
    "        return:\n",
    "        \"\"\"\n",
    "        # (batch_size * num_heads) * seq_len * (hidden_size / num_heads)\n",
    "        queries = self.transpose_qkv(self.W_q(queries))\n",
    "        keys = self.transpose_qkv(self.W_k(keys))\n",
    "        values = self.transpose_qkv(self.W_v(values))\n",
    "        # 重复张量的元素，用以支持多个注意力头的运算\n",
    "        # (batch_size * num_heads) * seq_len * seq_len\n",
    "        attention_mask = torch.repeat_interleave(attention_mask,\\\n",
    "            repeats=self.num_heads, dim=0)\n",
    "        # (batch_size * num_heads) * seq_len * (hidden_size / num_heads)\n",
    "        output = self.attention(queries, keys, values, attention_mask)\n",
    "        # batch * seq_len * hidden_size\n",
    "        output_concat = self.transpose_output(output)\n",
    "        return self.W_o(output_concat)\n",
    "\n",
    "# 两层前馈神经网络\n",
    "class PositionWiseFNN(nn.Module):\n",
    "    def __init__(self, hidden_size, intermediate_size):\n",
    "        super().__init__()\n",
    "        self.dense1 = nn.Linear(hidden_size, intermediate_size)\n",
    "        self.relu = nn.ReLU()\n",
    "        self.dense2 = nn.Linear(intermediate_size, hidden_size)\n",
    "        \n",
    "    def forward(self, X):\n",
    "        return self.dense2(self.relu(self.dense1(X)))\n",
    "\n",
    "# 层归一化\n",
    "class LayerNorm(nn.Module):\n",
    "    def __init__(self, normalized_shape, eps=1e-6):\n",
    "        super().__init__()\n",
    "        self.gamma = nn.Parameter(torch.ones(normalized_shape))\n",
    "        self.beta = nn.Parameter(torch.zeros(normalized_shape))\n",
    "        # 一个小量用于数值稳定（防止除0）\n",
    "        self.eps = eps\n",
    "        \n",
    "    def forward(self, hidden_states):\n",
    "        mean = torch.mean(hidden_states, -1, keepdim=True)\n",
    "        std = torch.std(hidden_states, -1, keepdim=True)\n",
    "        return self.gamma * (hidden_states - mean) / (std +\\\n",
    "            self.eps) + self.beta\n",
    "\n",
    "# 将两个输入相加并归一化\n",
    "class AddNorm(nn.Module):\n",
    "    def __init__(self, hidden_size, dropout):\n",
    "        super().__init__()\n",
    "        self.dropout = nn.Dropout(dropout)\n",
    "        self.layer_norm = LayerNorm(hidden_size)\n",
    "        \n",
    "    def forward(self, X, Y):\n",
    "        return self.layer_norm(self.dropout(Y) + X)\n",
    "    \n",
    "# 一个完整的Transformer层\n",
    "class TransformerLayer(nn.Module):\n",
    "    def __init__(self, hidden_size, num_heads, dropout, intermediate_size):\n",
    "        super().__init__()\n",
    "        self.self_attention = MultiHeadSelfAttention(hidden_size,\\\n",
    "            num_heads, dropout)\n",
    "        self.add_norm1 = AddNorm(hidden_size, dropout)\n",
    "        self.fnn = PositionWiseFNN(hidden_size, intermediate_size)\n",
    "        self.add_norm2 = AddNorm(hidden_size, dropout)\n",
    "    \n",
    "    def forward(self, X, attention_mask):\n",
    "        Y = self.add_norm1(X, self.self_attention(X, X, X, attention_mask))\n",
    "        return self.add_norm2(Y, self.fnn(Y))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "2fd3f8f4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 在Transformer模型基础上加上语言模型需要的输入输出、损失计算等\n",
    "class TransformerLM(nn.Module):\n",
    "    def __init__(self, vocab_size, max_len, hidden_size, num_layers,\\\n",
    "                 num_heads, dropout, intermediate_size):\n",
    "        super().__init__()\n",
    "        self.embedding_layer = EmbeddingLayer(vocab_size, max_len,\\\n",
    "            hidden_size)\n",
    "        self.num_layers = num_layers\n",
    "        # 使用ModuleList保存多个Transformer层，注意不能使用Python列表，\n",
    "        # Python列表保存的PyTorch变量无法自动求导\n",
    "        self.layers = nn.ModuleList([TransformerLayer(hidden_size,\\\n",
    "            num_heads, dropout, intermediate_size)\\\n",
    "            for _ in range(num_layers)])\n",
    "        self.output_layer = nn.Linear(hidden_size, vocab_size)\n",
    "        \n",
    "    def forward(self, input_ids):\n",
    "        # 这里实现的forward()函数一次只能处理一句话，\n",
    "        # 如果想要支持批次运算，实现起来会更复杂，也会引入冗余操作\n",
    "        seq_len = input_ids.size(0)\n",
    "        assert input_ids.ndim == 1 and seq_len <= \\\n",
    "            self.embedding_layer.max_len\n",
    "        \n",
    "        # 1 * seq_len\n",
    "        input_ids = torch.unsqueeze(input_ids, dim=0)\n",
    "        pos_ids = torch.unsqueeze(torch.arange(seq_len), dim=0)\n",
    "        # 定义下三角掩码，用于语言模型训练\n",
    "        # 1 * seq_len * seq_len\n",
    "        attention_mask = torch.unsqueeze(torch.tril(torch.ones((seq_len,\\\n",
    "            seq_len), dtype=torch.int32)), dim=0)\n",
    "        # 1 * seq_len * hidden_size\n",
    "        hidden_states = self.embedding_layer(input_ids, pos_ids)\n",
    "        for layer in self.layers:\n",
    "            hidden_states = layer(hidden_states, attention_mask)\n",
    "        outputs = self.output_layer(hidden_states)\n",
    "        \n",
    "        loss_fct = nn.CrossEntropyLoss(ignore_index=0)\n",
    "        loss = loss_fct(outputs[:, :-1].squeeze(),\\\n",
    "            input_ids[:, 1:].squeeze())\n",
    "        return loss"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "e459fc19",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "epoch-49, loss=0.2988: 100%|█| 50/50 [06:09<00:00,  7.39s/it\n"
     ]
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 训练TransformerLM，由于不再采取批次训练，因此不再使用RNNLM和data_loader\n",
    "def train_transformer_lm(data, model, epochs=50, learning_rate=1e-3):\n",
    "    optimizer = Adam(model.parameters(), lr=learning_rate)\n",
    "    model.zero_grad()\n",
    "    model.train()\n",
    "    \n",
    "    epoch_loss = []\n",
    "    with trange(epochs, desc='epoch', ncols=60) as pbar:\n",
    "        for epoch in pbar:\n",
    "            step_loss = []\n",
    "            np.random.shuffle(data)\n",
    "            for step, x in enumerate(data):\n",
    "                loss = model(torch.tensor(x, dtype=torch.long))\n",
    "                pbar.set_description(f'epoch-{epoch},'+\\\n",
    "                    f' loss={loss.item():.4f}')\n",
    "                loss.backward()\n",
    "                grad_clipping(model)\n",
    "                optimizer.step()\n",
    "                model.zero_grad()\n",
    "                step_loss.append(loss.item())\n",
    "            # 本章前面的模型训练使用batch_size为16，\n",
    "            # TransformerLM出于简便实现只能使用batch_size为1\n",
    "            # 因此TransformerLM每一步的损失方差会更大，\n",
    "            # 为便于对比，取每个epoch最后16个样本的平均损失\n",
    "            epoch_loss.append(np.mean(step_loss[-16:]))\n",
    "    \n",
    "    epoch_loss = np.array(epoch_loss)\n",
    "    plt.plot(range(len(epoch_loss)), epoch_loss)\n",
    "    plt.xlabel('training epoch')\n",
    "    plt.ylabel('loss')\n",
    "    plt.show()\n",
    "    \n",
    "sent_tokens = dataset.convert_tokens_to_ids()\n",
    "max_len=40\n",
    "for i, tokens in enumerate(sent_tokens):\n",
    "    tokens = tokens[:max_len]\n",
    "    tokens += [0] * (max_len - len(tokens))\n",
    "    sent_tokens[i] = tokens\n",
    "sent_tokens = np.array(sent_tokens)\n",
    "\n",
    "model = TransformerLM(vocab_size, max_len=40, hidden_size=128,\\\n",
    "    num_layers=1, num_heads=4, dropout=0., intermediate_size=512)\n",
    "train_transformer_lm(sent_tokens, model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b80cf087-4e78-4215-b66d-05ae296f42c3",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b82381a4-04a0-44c5-be53-40219ccb4551",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9d1096ac-63f6-4bfd-a6ac-f05c2a95938b",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "752c1849-2b20-4de8-9168-28468a7054cc",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
